---
title: ActionBarPrimitive
---

Buttons to interact with the message.

import { ParametersTable, DataAttributesTable } from "@/components/docs";
import { Code } from "@radix-ui/themes";

## Anatomy

```tsx
import { ActionBarPrimitive } from "@assistant-ui/react";

const UserMessageBar = () => (
  <ActionBarPrimitive.Root>
    <ActionBarPrimitive.Edit />
    <ActionBarPrimitive.Copy />
  </ActionBarPrimitive.Root>
);

const AssistantMessageBar = () => (
  <ActionBarPrimitive.Root>
    <ActionBarPrimitive.Reload />
    <ActionBarPrimitive.Copy />
  </ActionBarPrimitive.Root>
);
```

## API Reference

### Container

Containts all parts of the action bar.

This primitive renders a `<div>` element unless `asChild` is set.

<ParametersTable
  type="ActionBarPrimitiveRootProps"
  parameters={[
    {
      name: "asChild",
    },
    {
      name: "hideWhenRunning",
      type: "boolean",
      default: "false",
      description: (
        <span>
          Do not render the ActionBar when the thread is in running state.
        </span>
      ),
    },
    {
      name: "autohide",
      type: '"always" | "not-last" | "never"',
      default: '"never"',
      description: (
        <span>
          Do not render the ActionBar unless the mouse is hovering over the
          message.
          <br />
          <br />
          <Code>"always"</Code>: always autohide.
          <br />
          <Code>"not-last"</Code>; only autohide if the message is not the last
          one in the thread.
        </span>
      ),
    },
    {
      name: "autohideFloat",
      type: '"always" | "single-branch" | "never"',
      default: '"never"',
      description: (
        <span>
          Float the ActionBar during autohide.
          <br />
          <br />
          <Code>"always"</Code>: always float during autohide.
          <br />
          <Code>"single-branch"</Code>: only float if the message is the only
          one in the thread.
          <br />
          <br />
          Note: this only sets `data-floating` on the ActionBar. You need to set
          the appropriate styles on the ActionBar to make it float.
        </span>
      ),
    },
  ]}
/>

<DataAttributesTable
  data={[
    {
      attribute: "[data-floating]",
      values: "Present when floating",
    },
  ]}
/>

### Edit

Enables edit mode on user message.

This primitive renders a `<button>` element unless `asChild` is set.

<ParametersTable
  type="ActionBarPrimitiveEditProps"
  parameters={[
    {
      name: "asChild",
    },
  ]}
/>

### Reload

Regenerates the assistant message.

This primitive renders a `<button>` element unless `asChild` is set.

<ParametersTable
  type="ActionBarPrimitiveReloadProps"
  parameters={[
    {
      name: "asChild",
    },
  ]}
/>{" "}

### Copy

Copies the message to the clipboard.

This primitive renders a `<button>` element unless `asChild` is set.

<ParametersTable
  type="ActionBarPrimitiveCopyProps"
  parameters={[
    {
      name: "asChild",
    },
    {
      name: "copiedDuration",
      type: "number",
      description:
        "The duration in milliseconds to change the message status to 'copied'.",
      default: "3000",
    },
  ]}
/>

<DataAttributesTable
  data={[
    {
      attribute: "[data-copied]",
      values: "Present when the message was recently copied.",
    },
  ]}
/>

#### Copied state

Show a different icon for a few seconds after the message is copied.

```tsx
<ActionBarPrimitive.Copy>
  <AssistantIf condition={({ message }) => !message.isCopied}>
    <CopyIcon />
  </AssistantIf>
  <AssistantIf condition={({ message }) => message.isCopied}>
    <CopySuccessIcon />
  </AssistantIf>
</ActionBarPrimitive.Copy>
```

or using the `data-copied` attribute:

```tsx
<ActionBarPrimitive.Copy className="group">
  <CopyIcon className="group-data-[copied]:hidden" />
  <CheckIcon className="hidden group-data-[copied]:block" />
</ActionBarPrimitive.Copy>
```

### Speak

Plays the message text as speech.

This primitive renders a `<button>` element unless `asChild` is set.

<ParametersTable
  type="ActionBarPrimitiveSpeakProps"
  parameters={[
    {
      name: "asChild",
    },
  ]}
/>

### StopSpeaking

Stops the message text from being played as speech.

This primitive renders a `<button>` element unless `asChild` is set.

<ParametersTable
  type="ActionBarPrimitiveStopSpeakingProps"
  parameters={[
    {
      name: "asChild",
    },
  ]}
/>

### Feedback Positive

Shows a positive feedback submission button.

This primitive renders a `<button>` element unless `asChild` is set.

<ParametersTable
  type="ActionBarPrimitiveFeedbackPositiveProps"
  parameters={[
    {
      name: "asChild",
    },
  ]}
/>

<DataAttributesTable
  data={[
    {
      attribute: "[data-submitted]",
      values: "Present when positive feedback was submitted.",
    },
  ]}
/>

### Feedback Negative

Shows a negative feedback submission button.

This primitive renders a `<button>` element unless `asChild` is set.

<ParametersTable
  type="ActionBarPrimitiveFeedbackNegativeProps"
  parameters={[
    {
      name: "asChild",
    },
  ]}
/>

<DataAttributesTable
  data={[
    {
      attribute: "[data-submitted]",
      values: "Present when negative feedback was submitted.",
    },
  ]}
/>

### ExportMarkdown

Exports the message content as a Markdown file download by default, or calls a custom export handler when `onExport` is provided.

This primitive renders a `<button>` element unless `asChild` is set.

<ParametersTable
  type="ActionBarPrimitiveExportMarkdownProps"
  parameters={[
    {
      name: "asChild",
    },
    {
      name: "filename",
      type: "string",
      description:
        "The filename for the downloaded Markdown file. Defaults to 'message-{timestamp}.md'. Ignored when onExport is provided.",
    },
    {
      name: "onExport",
      type: "(content: string) => void | Promise<void>",
      description:
        "Optional callback function that receives the message content. When provided, overrides the default Markdown download behavior. Use this to implement custom export logic (PDF, JSON, TXT, etc.).",
    },
  ]}
/>

#### Examples

Default Markdown export:

```tsx
<ActionBarPrimitive.ExportMarkdown>
  <DownloadIcon />
  Export as Markdown
</ActionBarPrimitive.ExportMarkdown>
```

With custom filename:

```tsx
<ActionBarPrimitive.ExportMarkdown filename="chat-response.md">
  <DownloadIcon />
  Download
</ActionBarPrimitive.ExportMarkdown>
```

Export as PDF (with custom logic):

```tsx
<ActionBarPrimitive.ExportMarkdown
  onExport={async (content) => {
    const pdf = await generatePdf(content);
    downloadFile(pdf, "message.pdf");
  }}
>
  <FileIcon />
  Export PDF
</ActionBarPrimitive.ExportMarkdown>
```

Export as JSON:

```tsx
<ActionBarPrimitive.ExportMarkdown
  onExport={(content) => {
    const json = JSON.stringify({ content, timestamp: Date.now() });
    const blob = new Blob([json], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "message.json";
    a.click();
    URL.revokeObjectURL(url);
  }}
>
  <CodeIcon />
  Export JSON
</ActionBarPrimitive.ExportMarkdown>
```
